package com.smile.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.smile.commons.time.TimeUtils;
import com.smile.mapper.AirportDroneMapper;
import com.smile.mapper.AirportMapper;
import com.smile.mapper.FlightStatisticsMapper;
import com.smile.model.domain.FeisuanAirport;
import com.smile.model.domain.FeisuanFlightStatistics;
import com.smile.model.dto.request.GetStatisticsDataRequestDTO;
import com.smile.model.response.response.*;
import com.smile.service.StatisticsService;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    private FlightStatisticsMapper flightStatisticsMapper;

    @Autowired
    private AirportMapper airportMapper;

    @Autowired
    private AirportDroneMapper airportDroneMapper;

    @Override
    public GetStatisticsDataResponseDTO getStatisticsData(GetStatisticsDataRequestDTO requestDTO) {
        GetStatisticsDataResponseDTO responseDTO = new GetStatisticsDataResponseDTO();

        // 设置查询时间范围，如果没有提供则使用默认值
        LocalDate startDate = requestDTO.getStartTime() != null ?
                requestDTO.getStartTime().toLocalDate() : LocalDate.now().minusMonths(6);
        LocalDate endDate = requestDTO.getEndTime() != null ?
                requestDTO.getEndTime().toLocalDate() : LocalDate.now();

        // 1. 获取总体统计数据
        setOverallStatistics(responseDTO, startDate, endDate);

        // 2. 获取飞行详情统计（按月份）
        setFlyDetailStatistics(responseDTO, startDate, endDate);

        // 3. 获取机场排名数据
        setAirportRankings(responseDTO, startDate, endDate);

        return responseDTO;
    }

    /**
     * 设置总体统计数据
     */
    private void setOverallStatistics(GetStatisticsDataResponseDTO responseDTO, LocalDate startDate, LocalDate endDate) {
        // 查询所有机场的统计数据
        LambdaQueryWrapper<FeisuanFlightStatistics> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(FeisuanFlightStatistics::getStatisticsDate, startDate, endDate)
                .eq(FeisuanFlightStatistics::getDeleteStatus, 0);

        List<FeisuanFlightStatistics> statisticsList = flightStatisticsMapper.selectList(wrapper);

        // 计算总体数据
        long totalFlyTime = statisticsList.stream()
                .mapToLong(FeisuanFlightStatistics::getTotalTaskTime)
                .sum();

        long totalFlyDistance = statisticsList.stream()
                .mapToLong(stat -> stat.getTotalTaskDistance() != null ? stat.getTotalTaskDistance() : 0L)
                .sum();

        long totalTasks = statisticsList.stream()
                .mapToLong(stat -> stat.getTaskCount() != null ? stat.getTaskCount() : 0L)
                .sum();

        // 计算平均数据
        long avgSingleTaskTime = totalTasks > 0 ? totalFlyTime / totalTasks : 0L;
        long avgSingleTaskDistance = totalTasks > 0 ? totalFlyDistance / totalTasks : 0L;

        // 获取机场无人机数量
        long airportDroneNums = airportDroneMapper.selectCount(null);

        responseDTO.setTotalFlyTime(totalFlyTime);
        responseDTO.setTotalFlyDistance(totalFlyDistance);
        responseDTO.setAvgSingleTaskTime(avgSingleTaskTime);
        responseDTO.setAvgSingleTaskDistance(avgSingleTaskDistance);
        responseDTO.setTotalTasks(totalTasks);
        responseDTO.setAirportDroneNums(airportDroneNums);
    }

    /**
     * 设置飞行详情统计（按月份）
     */
    private void setFlyDetailStatistics(GetStatisticsDataResponseDTO responseDTO, LocalDate startDate, LocalDate endDate) {
        GetStatisticsDataResponseDTO.FlyDetailStatistics flyDetailStatistics = new GetStatisticsDataResponseDTO.FlyDetailStatistics();

        List<String> dates = new ArrayList<>();
        List<Long> totalFlyDistances = new ArrayList<>();
        List<Long> totalFlyTimes = new ArrayList<>();

        // 按月份统计
        LocalDate current = startDate.withDayOfMonth(1);
        while (!current.isAfter(endDate)) {
            LocalDate monthStart = current;
            LocalDate monthEnd = current.plusMonths(1).minusDays(1);

            // 查询该月的统计数据
            LambdaQueryWrapper<FeisuanFlightStatistics> wrapper = new LambdaQueryWrapper<>();
            wrapper.between(FeisuanFlightStatistics::getStatisticsDate, monthStart, monthEnd)
                    .eq(FeisuanFlightStatistics::getDeleteStatus, 0);

            List<FeisuanFlightStatistics> monthStatistics = flightStatisticsMapper.selectList(wrapper);

            long monthDistance = monthStatistics.stream()
                    .mapToLong(stat -> stat.getTotalTaskDistance() != null ? stat.getTotalTaskDistance() : 0L)
                    .sum();

            long monthTime = monthStatistics.stream()
                    .mapToLong(FeisuanFlightStatistics::getTotalTaskTime)
                    .sum();

            dates.add(current.format(DateTimeFormatter.ofPattern("yyyy-MM")));
            totalFlyDistances.add(monthDistance);
            totalFlyTimes.add(monthTime);

            current = current.plusMonths(1);
        }

        flyDetailStatistics.setDate(dates);
        flyDetailStatistics.setTotalFlyDistance(totalFlyDistances);
        flyDetailStatistics.setTotalFlyTime(totalFlyTimes);

        responseDTO.setFlyDetailStatistics(flyDetailStatistics);
    }

    /**
     * 设置机场排名数据
     */
    private void setAirportRankings(GetStatisticsDataResponseDTO responseDTO, LocalDate startDate, LocalDate endDate) {
        // 获取所有机场
        List<FeisuanAirport> airports = airportMapper.selectList(
                new LambdaQueryWrapper<FeisuanAirport>()
                        .eq(FeisuanAirport::getDeleteStatus, false)
        );

        Map<Long, String> airportNameMap = airports.stream()
                .collect(Collectors.toMap(FeisuanAirport::getId, FeisuanAirport::getAirportName));

        // 按机场统计飞行数据
        Map<Long, AirportStatistics> airportStatsMap = new HashMap<>();

        LambdaQueryWrapper<FeisuanFlightStatistics> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(FeisuanFlightStatistics::getStatisticsDate, startDate, endDate)
                .eq(FeisuanFlightStatistics::getDeleteStatus, 0);

        List<FeisuanFlightStatistics> statisticsList = flightStatisticsMapper.selectList(wrapper);

        for (FeisuanFlightStatistics stat : statisticsList) {
            Long airportId = stat.getAirportId();
            if (airportId != null) {
                AirportStatistics airportStat = airportStatsMap.computeIfAbsent(airportId,
                        k -> new AirportStatistics(airportNameMap.get(k)));

                airportStat.addDistance(stat.getTotalTaskDistance() != null ? stat.getTotalTaskDistance() : 0L);
                airportStat.addTime(stat.getTotalTaskTime());
                airportStat.addTaskCount(stat.getTaskCount() != null ? stat.getTaskCount() : 0L);
            }
        }

        // 按距离排名
        List<GetStatisticsAirportByFlyDistanceListResponseDTO> distanceRanking = airportStatsMap.values()
                .stream()
                .sorted((a, b) -> Long.compare(b.getTotalDistance(), a.getTotalDistance()))
                .limit(10)
                .map(stat -> {
                    GetStatisticsAirportByFlyDistanceListResponseDTO dto = new GetStatisticsAirportByFlyDistanceListResponseDTO();
                    dto.setAirportName(stat.getAirportName());
                    dto.setFlyDistance(stat.getTotalDistance());
                    dto.setSort((long) (airportStatsMap.values().stream()
                            .sorted((a, b) -> Long.compare(b.getTotalDistance(), a.getTotalDistance()))
                            .collect(Collectors.toList()).indexOf(stat) + 1));
                    return dto;
                })
                .collect(Collectors.toList());

        // 按时间排名
        List<GetStatisticsAirportByFlyTimesListResponseDTO> timeRanking = airportStatsMap.values()
                .stream()
                .sorted((a, b) -> Long.compare(b.getTotalTime(), a.getTotalTime()))
                .limit(10)
                .map(stat -> {
                    GetStatisticsAirportByFlyTimesListResponseDTO dto = new GetStatisticsAirportByFlyTimesListResponseDTO();
                    dto.setAirportName(stat.getAirportName());
                    dto.setTotalTaskTimes(TimeUtils.toChineseTime(stat.getTotalTime()));
                    dto.setSort((long) (airportStatsMap.values().stream()
                            .sorted((a, b) -> Long.compare(b.getTotalTime(), a.getTotalTime()))
                            .collect(Collectors.toList()).indexOf(stat) + 1));
                    return dto;
                })
                .collect(Collectors.toList());

        // 按架次排名
        List<GetStatisticsAirportByFlyCountsListResponseDTO> countRanking = airportStatsMap.values()
                .stream()
                .sorted((a, b) -> Long.compare(b.getTotalTaskCount(), a.getTotalTaskCount()))
                .limit(10)
                .map(stat -> {
                    GetStatisticsAirportByFlyCountsListResponseDTO dto = new GetStatisticsAirportByFlyCountsListResponseDTO();
                    dto.setAirportName(stat.getAirportName());
                    dto.setTotalTasks(stat.getTotalTaskCount());
                    dto.setSort((long) (airportStatsMap.values().stream()
                            .sorted((a, b) -> Long.compare(b.getTotalTaskCount(), a.getTotalTaskCount()))
                            .collect(Collectors.toList()).indexOf(stat) + 1));
                    return dto;
                })
                .collect(Collectors.toList());

        responseDTO.setGetStatisticsAirportListResponseDTOByFlyDistance(distanceRanking);
        responseDTO.setGetStatisticsAirportByFlyTimesListResponseDTOS(timeRanking);
        responseDTO.setGetStatisticsAirportListResponseDTOByFlyCount(countRanking);
    }

    /**
     * 机场统计内部类
     */
    @Getter
    private static class AirportStatistics {
        // Getters
        private final String airportName;
        private long totalDistance = 0L;
        private long totalTime = 0L;
        private long totalTaskCount = 0L;

        public AirportStatistics(String airportName) {
            this.airportName = airportName;
        }

        public void addDistance(long distance) {
            this.totalDistance += distance;
        }

        public void addTime(long time) {
            this.totalTime += time;
        }

        public void addTaskCount(long count) {
            this.totalTaskCount += count;
        }

    }
}
